import * as THREE from '../../build/three.module.js';
import {
  OrbitControls
} from '../../jsm/controls/OrbitControls.js';

const scene = new THREE.Scene();

// 几何体
const sphereGeo = new THREE.SphereGeometry(20, 25, 25);
const boxGeo = new THREE.BoxGeometry(20, 5, 5);
// 材质
const sphereMat = new THREE.MeshLambertMaterial({
  color: 0xff00ff,
  side: THREE.DoubleSide
});
const boxMat = new THREE.MeshLambertMaterial({
  color: 0xeeeeee,
  side: THREE.DoubleSide
});
// 模型组
const group = new THREE.Group();
const sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);
const boxMesh = new THREE.Mesh(boxGeo, boxMat);
sphereMesh.name = 'sphere';
boxMesh.name = 'box';
group.add(sphereMesh);
group.add(boxMesh);
scene.add(group);

/**
 * 构建关键帧轨道 KeyframeTrack
 *    关键帧轨道对象中总是存在两个数组
 *    times: 按顺序存储着改轨道的所有关键帧时间值
 *    values: 包含动画属性的在相应时间值时应更改的值
 * times 数组中存储的时间值时一个个离散的时间点，因此需要在两个时间点间插值
 * values 中的值应当对应哪个动画节点的那个属性，是通过轨道的 name 字段进行连接的
 */
const posKFT = new THREE.KeyframeTrack('box.position', [0, 10], [0, 0, 0, 150, 0, 0]);
const colorKFT = new THREE.KeyframeTrack('box.material.color', [10, 20], [1, 0, 0, 0, 0, 1]);
const scaleKFT = new THREE.KeyframeTrack('sphere.scale', [0, 20], [1, 1, 1, 3, 3, 3]);

/**
 * 创建剪辑对象 AnimationClip
 *    可重用的关键帧轨道集合
 */
const duration = 20; // 动画持续时长
const clip = new THREE.AnimationClip('default', duration, [
  posKFT, colorKFT, scaleKFT
]);

/**
 * 使用 AnimationAction 和 AnimationMixer 播放帧动画数据
 *    动画混合器 AnimationMixer 是用于场景中特定对象的动画播放器
 *        rootObject 播放动画所属的对象，还可以是外部加载的模型对象
 * 
 *    动画操作对象 AnimationAction 用于调度 AnimationClips 中的动画
 *        timeScale: 全局时间比例因子，可以通过设置为 0 和 1 来暂停/继续动画的播放，小于 0 时可反向播放
 */
const mixer = new THREE.AnimationMixer(group); // group作为参数，可以播放其内所有对象的动画
// 获取动画操作对象
const action = mixer.clipAction(clip); // 获取 AnimationAction 对象
action.timeScale = 10; // 时间比例因子
action.loop = THREE.LoopOnce; // 不循环播放：
action.clampWhenFinished = true; // 动画会停止在最后一帧
action.play(); // 开始播放

const al = new THREE.AmbientLight(0xffffff);
scene.add(al);

const axesH = new THREE.AxesHelper(400);
scene.add(axesH);

const k = innerWidth / innerHeight,
      s = 60,
      camera = new THREE.PerspectiveCamera(s, k, 1, 10000);
camera.position.set(400, 400, 400);
camera.lookAt(scene.position);

const renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xaaaaaa);
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

new OrbitControls(camera, renderer.domElement);

/**
 * 帧动画需要获取两次渲染间的时间间隔
 *    通过 Clock 类来获取
 */
const clock = new THREE.Clock();

(function render() {
  renderer.render(scene, camera);
  requestAnimationFrame(render);

  mixer.update(clock.getDelta());
})();